/**
 * This class returns all events to remind the user of his to-do's
 * It sorts all events
 * 1- Overdue Events
 * 2- Starred Events
 * 3- Regular Events
 * @author Harsha Narayan
 */


package action;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

import storage.DataManager;
import data.Event;


public class Reminder extends Action {

	Overdue overdueObj =  new Overdue();


	/**
	 * @param userCommand
	 * @return Event[] of all events, sorted to remind
	 */
	@Override
	public Event[] execute(String userCommand) {
		
		Event[] result = new Event[50];
		result = reminder(getAllEvents());
		return result;
	}

	/**
	 * 
	 * @param allEvents
	 * @return Event[] of all events sorted for reminding
	 */
	public Event[] reminder(Event[] allEvents) {

		if (allEvents == null || allEvents.length == 0) {
			return allEvents;
		}
		
		ArrayList<Event> overdueEvents = new ArrayList<Event>();
		ArrayList<Event> notOverdueEvents = new ArrayList<Event>();
		
		ArrayList<Event> starredEvents = new ArrayList<Event>();
		ArrayList<Event> notStarredEvents = new ArrayList<Event>();
		
		ArrayList<Event> sortedOverdue = new ArrayList<Event>();
		ArrayList<Event> sortedStarred = new ArrayList<Event>();
		ArrayList<Event> sortedRest = new ArrayList<Event>();
		
		ArrayList<Event> sortedAll = new ArrayList<Event>();


		Collections.addAll(overdueEvents, overdueObj.overdue(allEvents));
		notOverdueEvents = getNotOverdue(allEvents);
		starredEvents = getAllStarred(notOverdueEvents);
		notStarredEvents = getNotStarred(notOverdueEvents);
		
		
		sortedOverdue = sort(overdueEvents);
		sortedStarred = sort(starredEvents);
		sortedRest = sort(notStarredEvents);
		
		if(sortedOverdue != null)
			sortedAll.addAll(sortedOverdue);

		if(sortedStarred != null)
			sortedAll.addAll(sortedStarred);

		if(sortedRest != null)
			sortedAll.addAll(sortedRest);


		Event[] sortedArray = sortedAll.toArray(new Event[sortedAll.size()]);

		return sortedArray;

	}

	/**
	 * 
	 * @param allEvents
	 * @return ArrayList of events which are not overdue
	 */
	public ArrayList<Event> getNotOverdue(Event[] allEvents) {

		ArrayList<Event> notOverdueEvents = new ArrayList<Event>();
		ArrayList<Event> overdueEvents = new ArrayList<Event>();


		Collections.addAll(notOverdueEvents, allEvents);
		Collections.addAll(overdueEvents, overdueObj.overdue(allEvents));
		notOverdueEvents.removeAll(overdueEvents);

		return notOverdueEvents;

	}

	/**
	 * 
	 * @param allEvents
	 * @return ArrayList of all events which are not starred
	 */
	public ArrayList<Event> getNotStarred(ArrayList<Event> allEvents) {

		ArrayList<Event> starredEvents = new ArrayList<Event>();
		starredEvents = getAllStarred(allEvents);
		allEvents.removeAll(starredEvents);
		return allEvents;

	}


	/**
	 * 
	 * @param allEvents
	 * @return ArrayList of all starred events
	 */
	public ArrayList<Event> getAllStarred(ArrayList<Event> allEvents) {

		ArrayList<Event> starredEvents = new ArrayList<Event>();
		for(int i=0; i<allEvents.size(); i++) {
			if(allEvents.get(i).getStarred() == true) {

				starredEvents.add(allEvents.get(i));
			}

		}

		return starredEvents;

	}

	
	/**
	 * 
	 * @param listOfEvents
	 * @return sorted arraylist of events passes as param
	 */
	public ArrayList<Event> sort(ArrayList<Event> listOfEvents) {

		String[][] timeAndIdOfEvents = time_And_Id(listOfEvents);
		if(timeAndIdOfEvents == null)
			return null;
		if(timeAndIdOfEvents != null)
			sort2dArray(timeAndIdOfEvents);

		ArrayList<Event> sortedList = new ArrayList<Event>();
		for(int i=0; i< timeAndIdOfEvents.length;i++) {
			sortedList.add(DataManager.getEventById(timeAndIdOfEvents[i][1]));
		}

		return sortedList;
	}


	
	public String[][] time_And_Id(ArrayList<Event> arrayListOfEvents) {
		String[][] timeId = new String[arrayListOfEvents.size()][2];

		if(arrayListOfEvents.size() == 0)
			return null;

		for(int i=0; i<arrayListOfEvents.size(); i++) {

			timeId[i][0] = Long.toString(arrayListOfEvents.get(i).getStart().getTimeInMilli()); 
			timeId[i][1] = arrayListOfEvents.get(i).getId();
		}

		return timeId;

	}


	/**
	 * this function sorts a 2d array
	 * @param array2d - any 2d array
	 */
	public void sort2dArray (String[][] array2d) {

		Arrays.sort(array2d, new Comparator<String[]>() {
			@Override
			public int compare(final String[] entry1, final String[] entry2) {
				final String time1 = entry1[0];
				final String time2 = entry2[0];
				long value = Long.parseLong(time1) - Long.parseLong(time2);
				if (value < 0) {
					return -1;
				} else if (value == 0) {
					return 0;
				} else {
					return +1;
				}
			}
		});

	}


	/**
	 * 
	 * @return all events in storage as an array
	 */
	public static Event[] getAllEvents() {
		return DataManager.getAllEventsInStorage();
	}

	/**
	 * undo is irrelevant for this class
	 */
	@Override
	public Event[] undo() {
		return null;
	}

	/**
	 * undo is irrelevant for this class
	 */
	@Override
	public boolean isUndoable() {
		return false;
	}

	@Override
	public String errorMessage() {
		return "Reminders cannot be displayed";
	}

	/**
	 * @return string- command currently being executed
	 * in this case, reminder
	 */
	@Override
	public String getCommandName() {
		return "reminder";
	}


}
